package com.qding.park.manager.service.core.biz;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.mongodb.core.DocumentCallbackHandler;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.query.Update.Position;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
import com.qding.park.common.core.constant.MongodbConstant;
import com.qding.park.common.utils.DateUtils;
import com.qding.park.common.utils.ListUtil;
import com.qding.park.manager.pojo.TbHistoryRecord.RecordTypeEnum;

@Component("DemoBiz")
public class DemoBiz {
	public static class DemoUserTemp{
		private int parkId;

		private String orderId;

		private String carNum;
		
		private String parkName;
		
		private String usreId;

		public int getParkId() {
			return parkId;
		}

		public void setParkId(int parkId) {
			this.parkId = parkId;
		}

		public String getOrderId() {
			return orderId;
		}

		public void setOrderId(String orderId) {
			this.orderId = orderId;
		}

		public String getCarNum() {
			return carNum;
		}

		public void setCarNum(String carNum) {
			this.carNum = carNum;
		}

		public String getParkName() {
			return parkName;
		}

		public void setParkName(String parkName) {
			this.parkName = parkName;
		}

		public String getUsreId() {
			return usreId;
		}

		public void setUsreId(String usreId) {
			this.usreId = usreId;
		}
		
		
		
	}
	
	
	public static class DemoUserMonth {

		private int parkId;

		private String orderId;

		private String carNum;

		private int monthBuy;

		private String userId;

		private String parkName;

		private Date oldCardExpiration;

		public int getParkId() {
			return parkId;
		}

		public void setParkId(int parkId) {
			this.parkId = parkId;
		}

		public String getParkName() {
			return parkName;
		}

		public Date getOldCardExpiration() {
			return oldCardExpiration;
		}

		public void setOldCardExpiration(Date oldCardExpiration) {
			this.oldCardExpiration = oldCardExpiration;
		}

		public void setParkName(String parkName) {
			this.parkName = parkName;
		}

		public String getOrderId() {
			return orderId;
		}

		public void setOrderId(String orderId) {
			this.orderId = orderId;
		}

		public String getCarNum() {
			return carNum;
		}

		public void setCarNum(String carNum) {
			this.carNum = carNum;
		}

		public int getMonthBuy() {
			return monthBuy;
		}

		public void setMonthBuy(int monthBuy) {
			this.monthBuy = monthBuy;
		}

		public String getUserId() {
			return userId;
		}

		public void setUserId(String userId) {
			this.userId = userId;
		}

	}

	public static class DemoUserReserve {

		private int parkId;

		private String orderId;

		private String carNum;

		public int getParkId() {
			return parkId;
		}

		public void setParkId(int parkId) {
			this.parkId = parkId;
		}

		public String getOrderId() {
			return orderId;
		}

		public void setOrderId(String orderId) {
			this.orderId = orderId;
		}

		public String getCarNum() {
			return carNum;
		}

		public void setCarNum(String carNum) {
			this.carNum = carNum;
		}

	}

	public static class DemoUserSession {

//		private String userId;

		private int recordType;

		private List<DemoUserReserve> reserveOrder;

		private List<DemoUserMonth> monthOrder;
		
		private String memberId ;

//		public String getUserId() {
//			return userId;
//		}
//
//		public void setUserId(String userId) {
//			this.userId = userId;
//		}

		
		public int getRecordType() {
			return recordType;
		}

		public String getMemberId() {
			return memberId;
		}

		public void setMemberId(String memberId) {
			this.memberId = memberId;
		}

		public void setRecordType(int recordType) {
			this.recordType = recordType;
		}

		public List<DemoUserReserve> getReserveOrder() {
			return reserveOrder;
		}

		public void setReserveOrder(List<DemoUserReserve> reserveOrder) {
			this.reserveOrder = reserveOrder;
		}

		public List<DemoUserMonth> getMonthOrder() {
			return monthOrder;
		}

		public void setMonthOrder(List<DemoUserMonth> monthOrder) {
			this.monthOrder = monthOrder;
		}

	}

	public static final Logger logger = LoggerFactory.getLogger(DemoUserMonth.class);

	public static final int PARK_RECORD_TYPE = -100;// 车场
	public static final int CAR_RECORD_TYPE = -99;// 车辆

	public static final int TENERAT_PAY_TYPE = 4;// 代客缴费

	public static final int CARLOCK_TYPE = 5;// 锁车单

	public static final int PASS_TYPE = 6;// 通行记录

	public static final int INVITE_TYPE = 7;// 邀请记录

	public static final int USER_TYPE = 8;// 用户数据

	public static final int PARKRULE_TYPE = 9;// 车场规则

	@Autowired
	private MongoTemplate mongoTemplate;

	public DBObject demoData_findCar(String carNum) {
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;
		Criteria matchCrieria = new Criteria();
		matchCrieria.and("recordType").is(CAR_RECORD_TYPE);
		matchCrieria.and("carNum").is(carNum);
		Query query = new Query(matchCrieria);
		DBObject car = mongoTemplate.findOne(query, DBObject.class, demoApi_tablename);
		return car;
	}

	public void demoData_createMonOrder(String userId, DemoUserMonth month) {
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;
		Criteria matchCrieria = new Criteria();
		matchCrieria.and("memberId").is(userId);
		matchCrieria.and("recordType").is(this.USER_TYPE);
		// matchCrieria.and("members.userId").exists(false);
		Query query = Query.query(matchCrieria);
		Update update = new Update();
		update.push("monthOrder", month);
		update.set("updateDate", new Date());
		update.set("remark", "用户会话");
		update.set("recordType", this.USER_TYPE);
		logger.info("query:{}", query);
		logger.info("update:{}", update);
		mongoTemplate.upsert(query, update, demoApi_tablename);

	}
	
	public void demoData_createTempOrder(String userId, DemoUserTemp temp) {
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;
		Criteria matchCrieria = new Criteria();
		matchCrieria.and("memberId").is(userId);
		matchCrieria.and("recordType").is(this.USER_TYPE);
		// matchCrieria.and("members.userId").exists(false);
		Query query = Query.query(matchCrieria);
		Update update = new Update();
		update.push("tempOrder", temp);
		update.set("updateDate", new Date());
		update.set("recordType", this.USER_TYPE);
		update.set("remark", "用户会话");
		logger.info("query:{}", query);
		logger.info("update:{}", update);
		mongoTemplate.upsert(query, update, demoApi_tablename);

	}

	public void demoData_calMonthFee(String orderId, int monthNum) {
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;
		Criteria matchCrieria = new Criteria();
		matchCrieria.and("recordType").is(this.USER_TYPE);
		matchCrieria.and("monthOrder.orderId").is(orderId);
		Query query = Query.query(matchCrieria);
		Update update = new Update();
		update.set("monthOrder.$.monthBuy", monthNum);
		logger.info("query:{}", query);
		logger.info("update:{}", update);
		mongoTemplate.upsert(query, update, demoApi_tablename);
	}

	public void demoData_createReserveOrder(int parkId, String carNum, String userId, String orderId) {
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;
		Criteria matchCrieria = new Criteria();
		matchCrieria.and("memberId").is(userId);
		matchCrieria.and("recordType").is(this.USER_TYPE);
		// matchCrieria.and("members.userId").exists(false);
		Query query = Query.query(matchCrieria);
		Update update = new Update();
		DemoUserReserve reserve = new DemoUserReserve();
		reserve.setCarNum(carNum);
		reserve.setOrderId(orderId);
		reserve.setParkId(parkId);
		update.push("reserveOrder", reserve);
		update.set("updateDate", new Date());
		update.set("recordType", this.USER_TYPE);
		update.set("remark", "用户会话");
		logger.info("query:{}", query);
		logger.info("update:{}", update);
		mongoTemplate.upsert(query, update, demoApi_tablename);
	}

	public List<DBObject> demoData_hisAll(int jumpPage, int pageLength) {
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;
		Criteria matchCrieria = new Criteria();
		List<Integer> list = new ArrayList<Integer>();
		list.add(RecordTypeEnum.MONTHRENT_PAY.getCode());
		list.add(RecordTypeEnum.RESERVE_PAY.getCode());
		list.add(RecordTypeEnum.TEMP_PAY.getCode());
		list.add(this.TENERAT_PAY_TYPE);
		matchCrieria.and("recordType").in(list);
		Query query = Query.query(matchCrieria);
		query.with(new Sort(new Order(Direction.DESC, "feeTime")));
		query.skip((jumpPage - 1) * pageLength);
		query.limit(pageLength);

		return mongoTemplate.find(query, DBObject.class, demoApi_tablename);
	}

	public List<DBObject> demoData_his(int jumpPage, int pageLength, int... recordType) {
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;
		Criteria matchCrieria = new Criteria();
		List<Integer> list = new ArrayList<Integer>();
		for (int i = 0; i < recordType.length; i++) {
			list.add(recordType[i]);
		}
		matchCrieria.and("recordType").in(list);
		logger.info(matchCrieria.toString());
		Query query = Query.query(matchCrieria);
		query.with(new Sort(new Order(Direction.DESC, "feeTime")));
		query.skip((jumpPage - 1) * pageLength);
		query.limit(pageLength);

		return mongoTemplate.find(query, DBObject.class, demoApi_tablename);
	}

	public List<DBObject> demoData_getParkings() {

		String uri = getRequestUri();
		final List<DBObject> demoList = new ArrayList<DBObject>();
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;
		Criteria matchCrieria = new Criteria();
		matchCrieria.and("uri").is(uri);
		Query query = new Query(matchCrieria);
		query.with(new Sort(new Order(Direction.ASC, "order")));
		mongoTemplate.executeQuery(query, demoApi_tablename, new DocumentCallbackHandler() {
			@Override
			public void processDocument(DBObject dbObject) throws MongoException, DataAccessException {
				demoList.add(dbObject);
			}
		});
		return demoList;
	}

	public List<DBObject> demoData() {

		String uri = getRequestUri();
		final List<DBObject> demoList = new ArrayList<DBObject>();
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;

		Criteria matchCrieria = new Criteria();
		matchCrieria.and("uri").is(uri);
		Query query = new Query(matchCrieria);
		query.with(new Sort(new Order(Direction.ASC, "order")));
		mongoTemplate.executeQuery(query, demoApi_tablename, new DocumentCallbackHandler() {
			@Override
			public void processDocument(DBObject dbObject) throws MongoException, DataAccessException {
				demoList.add(dbObject);
			}
		});
		return demoList;
	}

	public DBObject demoData_record_findone(String carNum, int recordType) {

//		String uri = getRequestUri();
		final List<DBObject> demoList = new ArrayList<DBObject>();
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;

		Criteria matchCrieria = new Criteria();
//		matchCrieria.and("uri").is(uri);
		matchCrieria.and("carNum").is(carNum);
		matchCrieria.and("recordType").is(recordType);
		Query query = new Query(matchCrieria);
		// query.with(new Sort(new Order(Direction.ASC, "order")));
		DBObject data = mongoTemplate.findOne(query, DBObject.class, demoApi_tablename);
		return data;
	}
	
	public List<DBObject> car_find(String carNum) {

		final List<DBObject> demoList = new ArrayList<DBObject>();
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;

		Criteria matchCrieria = new Criteria();
		matchCrieria.and("carNum").is(carNum);
		matchCrieria.and("recordType").is(this.CAR_RECORD_TYPE);
		Query query = new Query(matchCrieria);
		List<DBObject> data = mongoTemplate.find(query, DBObject.class, demoApi_tablename);
		return data;
	}
	
	public DBObject demoData_record_findone(int parkId,String carNum, int recordType) {

		final List<DBObject> demoList = new ArrayList<DBObject>();
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;

		Criteria matchCrieria = new Criteria();
		matchCrieria.and("carNum").is(carNum);
		matchCrieria.and("parkId").is(parkId);
		matchCrieria.and("recordType").is(recordType);
		Query query = new Query(matchCrieria);
		DBObject data = mongoTemplate.findOne(query, DBObject.class, demoApi_tablename);
		return data;
	}

	public List<DBObject> demoData_record_findAll(int recordType) {

		String uri = getRequestUri();
		final List<DBObject> demoList = new ArrayList<DBObject>();
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;

		Criteria matchCrieria = new Criteria();
		matchCrieria.and("recordType").is(recordType);
		Query query = new Query(matchCrieria);
		List<DBObject> data = mongoTemplate.find(query, DBObject.class, demoApi_tablename);
		return data;
	}

	public List<DBObject> demoData_record_findAll(int recordType, int parkId) {

		String uri = getRequestUri();
		final List<DBObject> demoList = new ArrayList<DBObject>();
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;

		Criteria matchCrieria = new Criteria();
		matchCrieria.and("recordType").is(recordType);
		matchCrieria.and("parkId").is(parkId);
		Query query = new Query(matchCrieria);
		List<DBObject> data = mongoTemplate.find(query, DBObject.class, demoApi_tablename);
		return data;
	}

	public DBObject demoData_record_findone(String orderId) {

		// String uri = getRequestUri();
		final List<DBObject> demoList = new ArrayList<DBObject>();
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;

		Criteria matchCrieria = new Criteria();
		// matchCrieria.and("uri").is(uri);
		matchCrieria.and("orderId").is(orderId);
		Query query = new Query(matchCrieria);
		// query.with(new Sort(new Order(Direction.ASC, "order")));
		DBObject data = mongoTemplate.findOne(query, DBObject.class, demoApi_tablename);
		return data;
	}

	public List<DBObject> demoData_queryCarInfo(String carNum) {

		final List<DBObject> demoList = new ArrayList<DBObject>();
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;

		Criteria matchCrieria = new Criteria();
		matchCrieria.and("carNum").is(carNum);
		matchCrieria.and("recordType").is(this.CAR_RECORD_TYPE);
		Query query = new Query(matchCrieria);
		query.with(new Sort(new Order(Direction.ASC, "order")));
		mongoTemplate.executeQuery(query, demoApi_tablename, new DocumentCallbackHandler() {
			@Override
			public void processDocument(DBObject dbObject) throws MongoException, DataAccessException {
				demoList.add(dbObject);
			}
		});
		return demoList;
	}

	public String getRequestUri() {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		String requestUri = request.getRequestURI();
		return requestUri;

	}

	public List<DBObject> findMyCars(String userId){
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;
		
		List<DBObject> cars=this.demoData_record_findAll(this.CAR_RECORD_TYPE);
		Criteria matchCrieria = new Criteria();
		matchCrieria.and("memberId").is(userId);
		matchCrieria.and("recordType").is(this.USER_TYPE);
		Query query = new Query(matchCrieria);
		DemoUserSession  session=this.mongoTemplate.findOne(query, DemoUserSession.class, demoApi_tablename);
		
		List<DemoUserMonth>  months=session==null?null:session.getMonthOrder();
		
		Map<String,Integer>  carmonths=new HashMap<String,Integer>();
		if(!ListUtil.isEmpty(months)){
			for(DemoUserMonth  mo:months){
				int buymonth=mo.getMonthBuy();
				String carNum=mo.getCarNum();
				if(carmonths.containsKey(carNum)){
					carmonths.put(carNum, carmonths.get(carNum)+buymonth);
				}else{
					carmonths.put(carNum, buymonth);
				}
			}
		}
		
		
		for(DBObject car:cars){
			String num=(String) car.get("carNum");
			Date cardExpiration=(Date) car.get("cardExpiration");
			int montotal=(carmonths.get(num)==null?0:carmonths.get(num));
			car.put("cardExpiration", DateUtils.addMonths(cardExpiration, montotal));
		}
		
		return cars;
		
	}
	
//	public DBObject findCars(String userId,String carNum){
//		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;
//		DBObject car=this.demodata(carNum, this.CAR_RECORD_TYPE);
//		Criteria matchCrieria = new Criteria();
//		matchCrieria.and("memberId").is(userId);
//		matchCrieria.and("recordType").is(this.USER_TYPE);
//		Query query = new Query(matchCrieria);
//		DemoUserSession  session=this.mongoTemplate.findOne(query, DemoUserSession.class, demoApi_tablename);
//		
//		List<DemoUserMonth>  months=session.getMonthOrder();
//		
//		Map<String,Integer>  carmonths=new HashMap<String,Integer>();
//		if(!ListUtil.isEmpty(months)){
//			for(DemoUserMonth  mo:months){
//				int buymonth=mo.getMonthBuy();
//				String carNum01=mo.getCarNum();
//				if(carmonths.containsKey(carNum01)){
//					carmonths.put(carNum01, carmonths.get(carNum01)+buymonth);
//				}else{
//					carmonths.put(carNum01, buymonth);
//				}
//			}
//		}
//		
//		
//		String num=(String) car.get("carNum");
//		Date cardExpiration=(Date) car.get("cardExpiration");
//		int montotal=(carmonths.get(num)==null?0:carmonths.get(num));
//		car.put("cardExpiration", DateUtils.addMonths(cardExpiration, montotal));
//		
//		return car;
//		
//	}
	
	public List<DBObject> findCarInfo(String userId,String carNum){
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;
		
		List<DBObject> cars=this.car_find(carNum);
		Criteria matchCrieria = new Criteria();
		matchCrieria.and("memberId").is(userId);
		matchCrieria.and("recordType").is(this.USER_TYPE);
		Query query = new Query(matchCrieria);
		DemoUserSession  session=this.mongoTemplate.findOne(query, DemoUserSession.class, demoApi_tablename);
		
		List<DemoUserMonth>  months=session.getMonthOrder();
		
		for(DBObject car:cars){
			String num=(String) car.get("carNum");
			int parkId=(int) car.get("parkId");
			Date cardExpiration=(Date) car.get("cardExpiration");
			int montotal=getBuyMonth(months,parkId,carNum);
			car.put("cardExpiration", DateUtils.addMonths(cardExpiration, montotal));
		}
		
		return cars;
		
	}
	
	private int getBuyMonth(List<DemoUserMonth>  months,int parkId,String carNum){
		int monthBuy=0;
		
		if(!ListUtil.isEmpty(months)){
			
			for(DemoUserMonth m:months){
				int pId=m.getParkId();
				int  monthb=m.getMonthBuy();
				String car=m.getCarNum();
				if(pId==parkId&&carNum.equals(car)){
					monthBuy=monthBuy+monthb;
				}
			}
		}
		
		return monthBuy;
		
	}
	
	public DemoUserMonth findMonth(String orderId) {

		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;
		DBObject dbObject = new BasicDBObject();
		dbObject.put("monthOrder.orderId", orderId);
		dbObject.put("recordType", this.USER_TYPE);
		DBObject fieldObject = new BasicDBObject();
		fieldObject.put("monthOrder.$", 1);
		fieldObject.put("memberId", 1);
		Query query = new BasicQuery(dbObject, fieldObject);
		DemoUserSession session = mongoTemplate.findOne(query, DemoUserSession.class, demoApi_tablename);

		DemoUserMonth month = new DemoUserMonth();
		month.setUserId(session.getMemberId());
		month.setOrderId(orderId);
		month.setCarNum((session == null || ListUtil.isEmpty(session.getMonthOrder())) ? ""
				: session.getMonthOrder().get(0).getCarNum());
		month.setOldCardExpiration((session == null || ListUtil.isEmpty(session.getMonthOrder())) ? null
				: session.getMonthOrder().get(0).getOldCardExpiration());
		return month;
	}
	
	public DemoUserTemp findTemp(String orderId) {

		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;
		DBObject dbObject = new BasicDBObject();
		dbObject.put("tempOrder.orderId", orderId);
		dbObject.put("recordType", this.USER_TYPE);
		DBObject fieldObject = new BasicDBObject();
		fieldObject.put("tempOrder.$", 1);
		fieldObject.put("memberId", 1);
		Query query = new BasicQuery(dbObject, fieldObject);
		DemoUserSession session = mongoTemplate.findOne(query, DemoUserSession.class, demoApi_tablename);

		DemoUserTemp temp = new DemoUserTemp();
		temp.setUsreId(session.getMemberId());
		temp.setOrderId(orderId);
		return temp;
	}
	
	
	public void  clearSession(String userId){
		String demoApi_tablename = MongodbConstant.TABLENAME_DEMOAPI;
		
		Criteria matchCrieria = new Criteria();
		matchCrieria.and("recordType").is(this.USER_TYPE);
		matchCrieria.and("memberId").is(userId);
		Query query = Query.query(matchCrieria);
		Update update = new Update();
		update.unset("monthOrder");
		update.unset("tempOrder");
		update.unset("reserveOrder");
		logger.info("query:{}", query);
		logger.info("update:{}", update);
		mongoTemplate.updateMulti(query, update, demoApi_tablename);
	}
}
